#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>
#include "device.h"
#include "image.h"
#include "bmp.h"

//14byte文件头
typedef struct
{
	char    cfType[2];//文件类型，"BM"(0x4D42)
	int     cfSize;//文件大小（字节）
	int cfReserved;//保留，值为0
	int     cfoffBits;//数据区相对于文件头的偏移量（字节）
}__attribute__((packed)) BITMAPFILEHEADER;
//__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐

//    //40byte信息头
typedef struct
{
	char ciSize[4];//BITMAPFILEHEADER所占的字节数
	int  ciWidth;//宽度
	int  ciHeight;//高度
	char ciPlanes[2];//目标设备的位平面数，值为1
	int  ciBitCount;//每个像素的位数
	char ciCompress[4];//压缩说明
	char ciSizeImage[4];//用字节表示的图像大小，该数据必须是4的倍数
	char ciXPelsPerMeter[4];//目标设备的水平像素数/米
	char ciYPelsPerMeter[4];//目标设备的垂直像素数/米
	char ciClrUsed[4]; //位图使用调色板的颜色数
	char ciClrImportant[4]; //指定重要的颜色数，当该域的值等于颜色数时（或者等于0时），表示所有颜色都一样重要
}__attribute__((packed)) BITMAPINFOHEADER;

BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;

int xres=0,yres=0;
int width=0,height=0;
int ciBytesCount=0;
static int cursor_bitmap_format_convert(char *dst, char *src)
{
	int i, j;
	char *psrc = src;
	char *pdst = dst;
	char *p = psrc;

	int startX=((xres>width)?(xres-width)/2:0);
	int startY=((yres>height)?(yres-height)/2:0);

	p += (width * height * ciBytesCount);

	for (i = 0; i < (yres > height?height:yres); i++)
	{
		pdst = dst + ((startY + i + 1)*xres + startX + (xres > width?width:xres)) * 4;
			//定位开始显示的屏幕位置
		for (j = 0; j<width; j++)
		{
			pdst -= 4;
			p -= 3;
			pdst[0] = p[0];
			pdst[1] = p[1];
			pdst[2] = p[2];
			pdst[3] = 0;
		}

	}

	return 0;
}

int show_bmp(deviceInformation *g_device,imageInformation *image)
{
	int i;
	FILE *fp;
	int rc;
	long int location = 0, BytesPerLine = 0;
	char *bmp_buf = NULL;
	char *bmp_buf_dst = NULL;
	char * buf = NULL;
	int flen = 0;
	int ret = -1;
	int total_length = 0;

	FBCleanScreen(0, g_device);      /* 清屏lcd */
	printf("显示bmp图片\n");
	if (image->path == NULL)
	{
		printf("图片路径错误\n");
		return -1;
	}
	printf("图片路径 = %s\n", image->path);
	fp = fopen(image->path, "rb");
	if (fp == NULL)
	{
		printf("无法打开图片\n");
		return -1;
	}
	/* 求解文件长度 */
	fseek(fp, 0, SEEK_SET);
	fseek(fp, 0, SEEK_END);

	flen = ftell(fp);
	printf("图片长度： %d\n", flen);

	bmp_buf = (char*)calloc(1, flen - 54);
	if (bmp_buf == NULL)
	{
		printf("图片输出内存不够\n");
		return -1;
	}
	/* 再移位到文件头部 */
	fseek(fp, 0, SEEK_SET);
	//
	rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, fp);
	if (rc != 1)
	{
		printf("图片头读取错误！\n");
		fclose(fp);
		return(-2);
	}
	//
	//检测是否是bmp图像
	if (memcmp(FileHead.cfType, "BM", 2) != 0)
	{
		printf("不是BMP图片\n");
		fclose(fp);
		return(-3);
	}
	rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, fp);
	if (rc != 1)
	{
		printf("读取图片信息头错误！\n");
		fclose(fp);
		return(-4);
	}
	width=InfoHead.ciWidth;
	height = InfoHead.ciHeight;
	
	image->width = InfoHead.ciWidth;//图片宽度
	image->height = InfoHead.ciHeight;//图片高度
	xres=g_device->tFBVar.xres;
	yres=g_device->tFBVar.yres;
	
	ciBytesCount=(InfoHead.ciBitCount)/8;
	total_length = width * height * ciBytesCount;
	image->ciBitCount=InfoHead.ciBitCount;
	image->ciSizeImage=total_length;
	//跳转的数据区
	fseek(fp, FileHead.cfoffBits, SEEK_SET);
	//
	//每行字节数
	buf = bmp_buf;
	while ((ret = fread(buf, 1, total_length, fp)) >= 0)
	{
		if (ret == 0)
		{
			usleep(100);
			continue;
		}
		//	printf("ret = %d\n", ret);
		buf = ((char*)buf) + ret;
		total_length = total_length - ret;
		if (total_length == 0)
			break;
	}
	
	//BMP显示只需要device_fb0->pucFBMem
	cursor_bitmap_format_convert(g_device->pucFBMem, bmp_buf);

//	munmap(mmap_start, buffersize);
	free(bmp_buf);
	fclose(fp);
//	printf("show logo return 0\n");
	return 0;
}
